
#include "SSB_wifi.h"
#include "SSB_sys_def.h"
#include "esp_smartconfig.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_system.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include <string.h>
#include <stdlib.h>

static EventGroupHandle_t wifi_event_group;
extern wifi_config_t wifi_config;
static const int WIFI_CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
int ssb_auto_smart_config = 0;
int ssb_auto_connect_wifi=0;

extern int SSB_net_initialized;

void SSB_smartconfig_task(void *parm);
SSB_wifi_on_connection_change connection_change_cb;
SSB_wifi_scan_done_call_back wifi_scan_done_cb=NULL;

void SSB_wifi_restart(){
    extern wifi_config_t wifi_config;
    esp_wifi_disconnect();
    esp_wifi_stop();
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    ssb_auto_connect_wifi=1;
    esp_wifi_start();

}

void SSB_set_wifi(char *ssid,char *password){
    strcpy(&(wifi_config.sta.ssid),ssid);
    strcpy(&(wifi_config.sta.password),password);
    SSB_wifi_restart();
}

static esp_err_t SSB_wifi_event_handler(void *ctx, system_event_t *event)
{
    extern char ip_address[16];
    switch (event->event_id)
    {
    case SYSTEM_EVENT_STA_START:
        if ((strlen((char *)&(wifi_config.sta.ssid[0])) > 0) && ssb_auto_connect_wifi)
        {
            esp_wifi_connect();
        }
        else if (ssb_auto_smart_config == 1)
        {
            SSB_start_smart_config();
        }
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        SSB_net_initialized = 1;
        //ip_address
        strcpy(&ip_address[0], ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
        ESP_LOGI(SSB_TAG, "got ip:%s", &ip_address[0]);
        if (connection_change_cb != NULL)
        {
            connection_change_cb(SSB_NET_CONNECTED_STATE);
        }
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);

        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        SSB_net_initialized = 0;
        memset(&ip_address[0], 0, sizeof(ip_address));
        if (connection_change_cb != NULL)
        {
            connection_change_cb(SSB_NET_DISCONNECTED_STATE);
        }
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
        break;
    case SYSTEM_EVENT_SCAN_DONE:
    {
        ESP_LOGI(SSB_TAG, "WiFi Scan Completed!");
        ESP_LOGI(SSB_TAG, "Number of access points found: %d", event->event_info.scan_done.number);
        uint16_t apCount = event->event_info.scan_done.number;
        if (apCount > 0)
        {
            wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
            esp_wifi_scan_get_ap_records(&apCount, list);
            if(wifi_scan_done_cb!=NULL){
                wifi_scan_done_cb(apCount,list);
            }
            free(list);
        }else
        {
            if(wifi_scan_done_cb!=NULL){
                wifi_scan_done_cb(0,NULL);
            }
        }
        wifi_scan_done_cb=NULL;
        esp_wifi_scan_stop();
        break;
    }
    default:
        break;
    }
    return ESP_OK;
}

static void SSB_smartconfig_sc_callback(smartconfig_status_t status, void *pdata)
{
    switch (status)
    {
    case SC_STATUS_WAIT:
        ESP_LOGI(SSB_TAG, "SC_STATUS_WAIT");

        break;
    case SC_STATUS_FIND_CHANNEL:
        ESP_LOGI(SSB_TAG, "SC_STATUS_FINDING_CHANNEL");
        break;
    case SC_STATUS_GETTING_SSID_PSWD:
        ESP_LOGI(SSB_TAG, "SC_STATUS_GETTING_SSID_PSWD");
        break;
    case SC_STATUS_LINK:
        ESP_LOGI(SSB_TAG, "SC_STATUS_LINK");
        wifi_config_t *wifi_config = pdata;
        ESP_LOGI(SSB_TAG, "SSID:%s", wifi_config->sta.ssid);
        ESP_LOGI(SSB_TAG, "PASSWORD:%s", wifi_config->sta.password);
        //tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, "SSB001");
        ESP_ERROR_CHECK(esp_wifi_disconnect());
        ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_config));
        ESP_ERROR_CHECK(esp_wifi_connect());
        break;
    case SC_STATUS_LINK_OVER:
        ESP_LOGI(SSB_TAG, "SC_STATUS_LINK_OVER");
        if (pdata != NULL)
        {
            uint8_t phone_ip[4] = {0};
            memcpy(phone_ip, (uint8_t *)pdata, 4);
            ESP_LOGI(SSB_TAG, "Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]);
        }
        xEventGroupSetBits(wifi_event_group, ESPTOUCH_DONE_BIT);
        break;
    default:
        break;
    }
}

void SSB_scan_wifi_ap(SSB_wifi_scan_done_call_back cb)
{
    wifi_scan_done_cb=cb;
    wifi_scan_config_t scanConf = {
        .ssid = NULL,
        .bssid = NULL,
        .channel = 0,
        .show_hidden = 1};
    ESP_LOGI(SSB_TAG, "Starting to Scan Wifi Acess Point");
    esp_wifi_scan_start(&scanConf, 0);
}

void SSB_smartconfig_task(void *parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS));
    ESP_ERROR_CHECK(esp_smartconfig_start(SSB_smartconfig_sc_callback));
    while (1)
    {
        uxBits = xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if (uxBits & WIFI_CONNECTED_BIT)
        {
            ESP_LOGI(SSB_TAG, "WiFi Connected to ap");
        }
        if (uxBits & ESPTOUCH_DONE_BIT)
        {
            esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
            esp_smartconfig_stop();
            ESP_LOGI(SSB_TAG, "smartconfig over");
            vTaskDelete(NULL);
        }
    }
}

void SSB_start_smart_config()
{
    ESP_LOGI(SSB_TAG, "Start smart config");
    xTaskCreate(SSB_smartconfig_task, "SSB_smartconfig_task", 4096, NULL, 3, NULL);
}

void SSB_init_wifi(SSB_wifi_on_connection_change connection_change, 
    int auto_smart_config,int auto_connect)
{
    connection_change_cb = connection_change;
    SSB_net_initialized = 0;
    ssb_auto_connect_wifi=auto_connect;
    ssb_auto_smart_config = auto_smart_config;
    wifi_event_group = xEventGroupCreate();
    esp_event_loop_init(SSB_wifi_event_handler, NULL);
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    esp_wifi_set_storage(WIFI_STORAGE_FLASH);
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
    ESP_LOGI(SSB_TAG, "Flash storage wifi:ssid=%s", wifi_config.sta.ssid);
    esp_wifi_start();
}

int SSB_is_has_wifi_configuration()
{
    if (strlen((char *)&(wifi_config.sta.ssid[0])) > 0)
    {
        return 1;
    }
    return 0;
}

void SSB_reset_wifi_configuration()
{
    memset(wifi_config.sta.ssid, '\0', sizeof(wifi_config.sta.ssid));
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
}

// #include "freertos/FreeRTOS.h"
// #include "esp_wifi.h"
// #include "esp_system.h"
// #include "esp_event_loop.h"
// #include "nvs_flash.h"
// #include "esp_log.h"
// #include <stdio.h>
// #include "freertos/FreeRTOS.h"

// static char* get_authmode(wifi_auth_mode_t authmode)
// {
// 	char *mode_name[]={"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "MAX"};
// 	return mode_name[authmode];
// }

// esp_err_t event_handler(void *ctx, system_event_t *event)
// {
//

// 	return ESP_OK;

// }

// int app_main(void)
// {
// 	//Initiliaze the NVS Flash
// 	nvs_flash_init();

// 	//Initialize the TCP Stack
// 	tcpip_adapter_init();

// 	//Initialize the system event handler
// 	ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

// 	//Config the wifi
// 	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
// 	ESP_ERROR_CHECK(esp_wifi_init(&cfg));

// 	//Config RAM as the wifi parameters storage
// 	ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));

// 	//Wifi as Station Mode
// 	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

// 	//Start wifi
// 	ESP_ERROR_CHECK(esp_wifi_start());

// 	//let us test a wifi scan ...

// 	return 0;
// }